<template>
  <div class="min-h-screen bg-gradient-to-br from-purple-900 via-blue-900 to-indigo-900 flex items-center justify-center p-4" style="width: 1200px">
    <!-- 开始页面 -->
    <div v-if="gameState === 'menu'" class="text-center space-y-8 animate-fade-in">
      <div class="space-y-4">
        <h1 class="text-6xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-green-400 to-blue-500 animate-pulse">
          🐍 贪吃蛇大冒险
        </h1>
        <p class="text-xl text-gray-300">收集食物，避开障碍，成为最强的蛇！</p>
      </div>

      <div class="bg-black/30 backdrop-blur-sm rounded-2xl p-6 border border-white/20">
        <h3 class="text-2xl font-bold text-white mb-4">🏆 最高分记录</h3>
        <p class="text-4xl font-bold text-yellow-400">{{ highScore }}</p>
      </div>

      <div class="space-y-4">
        <h3 class="text-xl font-bold text-white">🎮 游戏说明</h3>
        <div class="grid grid-cols-1 md:grid-cols-2 gap-4 text-sm text-gray-300">
          <div class="bg-black/20 rounded-lg p-4">
            <p class="font-bold text-green-400">🍎 红色食物</p>
            <p>+10分，增长身体</p>
          </div>
          <div class="bg-black/20 rounded-lg p-4">
            <p class="font-bold text-blue-400">⚡ 蓝色道具</p>
            <p>+20分，临时加速</p>
          </div>
          <div class="bg-black/20 rounded-lg p-4">
            <p class="font-bold text-yellow-400">💎 金色道具</p>
            <p>+50分，超级奖励</p>
          </div>
          <div class="bg-black/20 rounded-lg p-4">
            <p class="font-bold text-purple-400">🔮 紫色道具</p>
            <p>+30分，临时无敌</p>
          </div>
        </div>

        <div class="bg-black/20 rounded-lg p-4 mt-4">
          <p class="font-bold text-cyan-400">🖱️ 鼠标控制</p>
          <p>移动鼠标控制蛇的方向，可以任意角度移动！</p>
        </div>

        <div class="bg-black/20 rounded-lg p-4 mt-4">
          <p class="font-bold text-orange-400">🗺️ 大地图模式</p>
          <p>在2000x1200的大地图中探索，视窗会跟随蛇移动！</p>
        </div>
      </div>

      <button
          @click="startGame"
          class="bg-gradient-to-r from-green-500 to-blue-600 hover:from-green-600 hover:to-blue-700 text-white font-bold py-4 px-8 rounded-full text-xl transition-all duration-300 transform hover:scale-105 shadow-lg"
      >
        🚀 开始游戏
      </button>
    </div>

    <!-- 游戏界面 -->
    <div v-else-if="gameState === 'playing' || gameState === 'paused'" class="space-y-4">
      <!-- 游戏信息栏 -->
      <div class="flex justify-between items-center bg-black/30 backdrop-blur-sm rounded-xl p-4 border border-white/20">
        <div class="flex items-center space-x-6">
          <div class="text-center">
            <p class="text-sm text-gray-400">得分</p>
            <p class="text-2xl font-bold text-green-400">{{ score }}</p>
          </div>
          <div class="text-center">
            <p class="text-sm text-gray-400">长度</p>
            <p class="text-2xl font-bold text-blue-400">{{ snake.length }}</p>
          </div>
          <div class="text-center">
            <p class="text-sm text-gray-400">最高分</p>
            <p class="text-2xl font-bold text-yellow-400">{{ highScore }}</p>
          </div>
          <div class="text-center">
            <p class="text-sm text-gray-400">食物数量</p>
            <p class="text-2xl font-bold text-orange-400">{{ foods.length }}</p>
          </div>
          <div class="text-center">
            <p class="text-sm text-gray-400">位置</p>
            <p class="text-sm font-bold text-cyan-400">{{ Math.round(snake[0]?.x || 0) }}, {{ Math.round(snake[0]?.y || 0) }}</p>
          </div>
        </div>

        <div class="flex items-center space-x-4">
          <!-- 食物刷新倒计时 -->
          <div class="flex items-center space-x-2 bg-orange-600/30 rounded-lg px-3 py-2">
            <span class="text-orange-300">🍎 刷新</span>
            <span class="text-xs text-orange-200">{{ Math.ceil(foodRefreshCountdown / 1000) }}s</span>
          </div>

          <button
              @click="backToMenu"
              class="bg-red-600 hover:bg-red-700 text-white font-bold py-2 px-4 rounded-lg transition-colors"
          >
            🏠 菜单
          </button>
        </div>
      </div>

      <!-- 游戏画布和小地图容器 -->
      <div class="flex gap-4">
        <!-- 游戏画布 -->
        <div class="relative">
          <!-- Toast 通知组件 - 显示在画布右上角 -->
          <div class="absolute top-4 right-4 z-50 space-y-2 pointer-events-none">
            <div
                v-for="toast in toasts"
                :key="toast.id"
                class="bg-white/90 backdrop-blur-sm rounded-lg shadow-lg p-3 border-l-4 transform transition-all duration-300 pointer-events-auto"
                :style="{ borderLeftColor: toast.borderColor }"
            >
              <div class="flex items-center space-x-2">
                <div class="text-lg">{{ toast.icon }}</div>
                <div class="flex-1">
                  <h4 class="font-bold text-gray-800 text-sm">{{ toast.title }}</h4>
                  <p class="text-xs text-gray-600">{{ toast.description }}</p>
                  <div v-if="toast.duration > 0" class="mt-1">
                    <div class="w-full bg-gray-200 rounded-full h-1">
                      <div
                          class="h-1 rounded-full transition-all duration-100"
                          :style="{ width: toast.progress + '%', backgroundColor: toast.progressColor }"
                      ></div>
                    </div>
                    <p class="text-xs text-gray-500 mt-1">剩余: {{ Math.ceil(toast.remainingTime / 1000) }}秒</p>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <canvas
              ref="gameCanvas"
              :width="viewportWidth"
              :height="viewportHeight"
              class="border-4 border-white/30 rounded-xl bg-gradient-to-br from-gray-900 to-gray-800 shadow-2xl cursor-none"
              @keydown="handleKeyPress"
              @mousemove="handleMouseMove"
              @mouseenter="handleMouseEnter"
              @mouseleave="handleMouseLeave"
              tabindex="0"
          ></canvas>

          <!-- 鼠标指示器 -->
          <div
              v-if="mousePosition.x !== null && gameState === 'playing'"
              class="absolute pointer-events-none"
              :style="{
              left: mousePosition.x + 'px',
              top: mousePosition.y + 'px',
              transform: 'translate(-50%, -50%)'
            }"
          >
            <div class="w-3 h-3 bg-cyan-400 rounded-full animate-ping"></div>
            <div class="absolute inset-0 w-3 h-3 bg-cyan-400 rounded-full"></div>
          </div>

          <!-- 暂停覆盖层 -->
          <div v-if="gameState === 'paused'" class="absolute inset-0 bg-black/50 backdrop-blur-sm rounded-xl flex items-center justify-center">
            <div class="text-center space-y-4">
              <h2 class="text-4xl font-bold text-white">⏸️ 游戏暂停</h2>
              <p class="text-gray-300">按空格键或点击继续按钮恢复游戏</p>
            </div>
          </div>
        </div>

        <!-- 小地图 -->
        <div class="bg-black/30 backdrop-blur-sm rounded-xl p-4 border border-white/20">
          <h3 class="text-white font-bold mb-2 text-center">🗺️ 地图</h3>
          <canvas
              ref="miniMapCanvas"
              :width="200"
              :height="120"
              class="border-2 border-white/20 rounded-lg bg-gray-800"
          ></canvas>
          <div class="mt-2 text-xs text-gray-400 text-center">
            <p>大地图: {{ mapWidth }}x{{ mapHeight }}</p>
            <p>视窗: {{ viewportWidth }}x{{ viewportHeight }}</p>
          </div>
        </div>
      </div>

      <!-- 移动控制按钮（移动端） -->
      <div class="grid grid-cols-3 gap-2 max-w-xs mx-auto md:hidden">
        <div></div>
        <button @click="changeDirection('up')" class="bg-white/20 hover:bg-white/30 text-white font-bold py-3 px-4 rounded-lg">⬆️</button>
        <div></div>
        <button @click="changeDirection('left')" class="bg-white/20 hover:bg-white/30 text-white font-bold py-3 px-4 rounded-lg">⬅️</button>
        <div></div>
        <button @click="changeDirection('right')" class="bg-white/20 hover:bg-white/30 text-white font-bold py-3 px-4 rounded-lg">➡️</button>
        <div></div>
        <button @click="changeDirection('down')" class="bg-white/20 hover:bg-white/30 text-white font-bold py-3 px-4 rounded-lg">⬇️</button>
        <div></div>
      </div>
    </div>

    <!-- 游戏结束页面 -->
    <div v-else-if="gameState === 'gameOver'" class="text-center space-y-8 animate-fade-in">
      <div class="space-y-4">
        <h1 class="text-5xl font-bold text-red-500 animate-bounce">💀 游戏结束</h1>
        <div class="bg-black/30 backdrop-blur-sm rounded-2xl p-6 border border-white/20 space-y-4">
          <p class="text-2xl text-white">本次得分</p>
          <p class="text-5xl font-bold text-green-400">{{ score }}</p>
          <p class="text-xl text-white">蛇的长度: {{ snake.length }}</p>
          <p class="text-lg text-cyan-400">最远到达: {{ Math.round(maxDistance) }} 像素</p>

          <div v-if="score === highScore && score > 0" class="animate-pulse">
            <p class="text-2xl font-bold text-yellow-400">🎉 新纪录！</p>
          </div>
        </div>
      </div>

      <div class="flex flex-col sm:flex-row gap-4 justify-center">
        <button
            @click="startGame"
            class="bg-gradient-to-r from-green-500 to-blue-600 hover:from-green-600 hover:to-blue-700 text-white font-bold py-3 px-6 rounded-full text-lg transition-all duration-300 transform hover:scale-105"
        >
          🔄 再来一局
        </button>
        <button
            @click="backToMenu"
            class="bg-gradient-to-r from-purple-500 to-pink-600 hover:from-purple-600 hover:to-pink-700 text-white font-bold py-3 px-6 rounded-full text-lg transition-all duration-300 transform hover:scale-105"
        >
          🏠 返回菜单
        </button>
      </div>
    </div>
  </div>
</template>

<script>

export default {
  data() {
    return {
      gameState: 'menu', // 'menu', 'playing', 'paused', 'gameOver'
      //开房需要的属性
      handler: 'sendPlayerAction',
      ws: null,
      players: [],
      roomId: null,
      // 大地图尺寸
      mapWidth: 2000,
      mapHeight: 1200,
      // 视窗尺寸
      viewportWidth: 600,
      viewportHeight: 400,
      // 摄像机位置
      camera: { x: 0, y: 0 },
      gridSize: 20,
      snake: [{ x: 1000, y: 600 }], // 从地图中心开始
      direction: { x: 1, y: 0 },
      nextDirection: { x: 1, y: 0 },
      foods: [],
      powerUps: [],
      score: 0,
      highScore: 0,
      maxDistance: 0, // 记录最远距离
      gameSpeed: 150,
      baseSpeed: 150,
      powerUpEffect: {
        active: false,
        type: '',
        name: '',
        duration: 0,
        startTime: 0
      },
      gameLoopInterval: null,
      powerUpSpawnTimer: null,
      powerUpRemovalTimer: null,
      foodRefreshTimer: null,
      foodRefreshCountdown: 5000,
      foodRefreshInterval: 5000,
      powerUpTypes: {
        speed: {
          name: '⚡ 加速',
          color: '#3B82F6',
          points: 20,
          duration: 5000,
          icon: '⚡',
          effect: (snake) => { return Math.min(6, snake + 1); },
          reset: () => 2
        },
        golden: {
          name: '💎 黄金',
          color: '#F59E0B',
          points: 50,
          duration: 0,
          icon: '💎',
          effect: (snake) => snake,
          reset: () => 2
        },
        invincible: {
          name: '🔮 无敌',
          color: '#8B5CF6',
          points: 30,
          duration: 3000,
          icon: '🔮',
          effect: (snake) => snake,
          reset: () => 2
        },
        slow: {
          name: '🐌 减速',
          color: '#10B981',
          points: 15,
          duration: 4000,
          icon: '🐌',
          effect: (snake) => Math.max(1, snake - 0.5),
          reset: () => 2
        }
      },
      animationProgress: 0,
      lastUpdateTime: 0,
      smoothMovement: true,
      frameId: null,
      mousePosition: { x: null, y: null },
      mouseControl: true,
      snakeSpeed: 2,
      segmentDistance: 15,
      // Toast 通知系统
      toasts: [],
      toastIdCounter: 0,
      toastUpdateInterval: null,
      activeEffects: [] // 跟踪所有活跃的道具效果
    }
  },
  mounted() {
    // 加载本地存储的最高分
    this.highScore = parseInt(localStorage.getItem('snakeHighScore') || '0')

    // 添加键盘事件监听
    window.addEventListener('keydown', this.handleKeyPress)

    // 启动 toast 更新定时器
    this.startToastUpdater()

    // 初始绘制一次菜单背景
    this.$nextTick(() => {
      if (this.$refs.gameCanvas && this.gameState === 'playing') {
        this.draw()
      }
    })

    // 明确指定path
    this.ws = new WebSocket('ws://localhost:8090/ws');

    this.ws.onopen = () => {
      // 加入房间
      const joinData = JSON.stringify({ type: 'joinRoom', maxPlayers: 5 });
      this.ws.send(joinData);
    };

    this.ws.onmessage = (event) => {
      const data = JSON.parse(event.data);
      switch (data.type) {
        case 'roomId':
          this.roomId = data.roomId;
          break;
        case 'playerList':
          this.players = data.players || [];
          break;
        case 'gameUpdate':
          if (data) {
            this.updateGameState(data);
          } else {
            console.warn('Received gameUpdate without gameState', data);
          }
          break;
        default:
          console.log('Unknown message type:', data.type);
      }
    };

    this.ws.onerror = (error) => {
      console.error('WebSocket error:', error);
    };

    this.ws.onclose = () => {
      console.log('WebSocket connection closed');
    };
  },
  beforeUnmount() {
    // 移除事件监听
    window.removeEventListener('keydown', this.handleKeyPress)

    // 清除所有定时器
    this.clearAllTimers()

    // 清除 toast 更新定时器
    if (this.toastUpdateInterval) {
      clearInterval(this.toastUpdateInterval)
    }

    // 断开 WebSocket 连接
    if (this.ws) {
      this.ws.close();
    }
  },
  methods: {
    // 更新游戏状态
    updateGameState(gameState) {
      if (!gameState) {
        console.warn('updateGameState called with undefined gameState');
        return;
      }

      this.players = gameState.players;
      // this.foods = gameState.foods;
      this.powerUps = gameState.powerUps;

      // 更新其他玩家的蛇数据（假设每个玩家对象中有snake属性）
      this.players.forEach(player => {
        if (player.id !== this.ws.url) { // 排除自己
          player.snake = gameState.players.find(p => p.id === player.id)?.snake || [];
        }
      });
    },
    // 发送玩家操作
    sendPlayerAction() {
      const action = {
        type: 'playerAction',
        direction: this.nextDirection,
        snake: this.snake,
        score: this.score,
        playerId: this.ws.url // 包含玩家ID
      };
      if (this.ws.readyState === WebSocket.OPEN) {
        this.ws.send(JSON.stringify(action));
      }
    },
    // 更新摄像机位置，跟随蛇头
    updateCamera() {
      const head = this.snake[0]

      // 摄像机跟随蛇头，但保持在地图边界内
      this.camera.x = Math.max(0, Math.min(this.mapWidth - this.viewportWidth, head.x - this.viewportWidth / 2))
      this.camera.y = Math.max(0, Math.min(this.mapHeight - this.viewportHeight, head.y - this.viewportHeight / 2))
    },

    // 世界坐标转换为屏幕坐标
    worldToScreen(worldX, worldY) {
      return {
        x: worldX - this.camera.x,
        y: worldY - this.camera.y
      }
    },

    // 屏幕坐标转换为世界坐标
    screenToWorld(screenX, screenY) {
      return {
        x: screenX + this.camera.x,
        y: screenY + this.camera.y
      }
    },

    // 检查对象是否在视窗内
    isInViewport(worldX, worldY, margin = 50) {
      return worldX >= this.camera.x - margin &&
          worldX <= this.camera.x + this.viewportWidth + margin &&
          worldY >= this.camera.y - margin &&
          worldY <= this.camera.y + this.viewportHeight + margin
    },

    // Toast 通知系统方法
    showToast(title, description, duration = 3000, icon = '🎉', borderColor = '#8b5cf6', progressColor = '#8b5cf6') {
      const toast = {
        id: ++this.toastIdCounter,
        title,
        description,
        duration,
        icon,
        borderColor,
        progressColor,
        startTime: Date.now(),
        progress: 100,
        remainingTime: duration
      }

      this.toasts.push(toast)

      // 如果是瞬时效果，自动移除
      if (duration > 0 && duration < 5000) {
        setTimeout(() => {
          this.removeToast(toast.id)
        }, duration)
      }

      return toast.id
    },

    removeToast(toastId) {
      const index = this.toasts.findIndex(t => t.id === toastId)
      if (index > -1) {
        this.toasts.splice(index, 1)
      }
    },

    startToastUpdater() {
      this.toastUpdateInterval = setInterval(() => {
        const now = Date.now()
        this.toasts.forEach(toast => {
          if (toast.duration > 0) {
            const elapsed = now - toast.startTime
            toast.remainingTime = Math.max(0, toast.duration - elapsed)
            toast.progress = (toast.remainingTime / toast.duration) * 100

            // 如果时间到了，移除 toast
            if (toast.remainingTime <= 0) {
              this.removeToast(toast.id)
            }
          }
        })
      }, 100)
    },

    // 开始游戏
    startGame() {
      this.gameState = 'playing'
      this.resetGame()
      this.$nextTick(() => {
        const canvas = this.$refs.gameCanvas
        if (canvas) {
          canvas.focus()
          this.startGameLoop()
          this.startPowerUpSpawn()
          this.startFoodRefresh()

          // 立即绘制一次，确保画面显示
          this.draw()
          this.drawMiniMap()
        }
      })
    },

    // 重置游戏
    resetGame() {
      this.snake = [{x: this.mapWidth / 2, y: this.mapHeight / 2}] // 从地图中心开始
      this.direction = {x: 1, y: 0}
      this.nextDirection = {x: 1, y: 0}
      this.score = 0
      this.maxDistance = 0
      this.gameSpeed = this.baseSpeed
      this.powerUps = []
      this.foods = []
      this.powerUpEffect = {active: false, type: '', name: '', duration: 0}
      this.mousePosition = {x: null, y: null}
      this.foodRefreshCountdown = this.foodRefreshInterval
      this.activeEffects = []
      this.snakeSpeed = 2

      // 重置摄像机位置
      this.updateCamera()

      // 清除所有 toast
      this.toasts = []

      // 清除所有定时器
      this.clearAllTimers()

      // 生成初始食物
      this.generateFoods()
    },

    // 清除所有定时器
    clearAllTimers() {
      if (this.gameLoopInterval) {
        clearInterval(this.gameLoopInterval)
        this.gameLoopInterval = null
      }
      if (this.frameId) {
        cancelAnimationFrame(this.frameId)
        this.frameId = null
      }
      if (this.powerUpSpawnTimer) {
        clearTimeout(this.powerUpSpawnTimer)
        this.powerUpSpawnTimer = null
      }
      if (this.powerUpRemovalTimer) {
        clearTimeout(this.powerUpRemovalTimer)
        this.powerUpRemovalTimer = null
      }
      if (this.foodRefreshTimer) {
        clearTimeout(this.foodRefreshTimer)
        this.foodRefreshTimer = null
      }
    },

    // 生成多个食物
    generateFoods() {
      this.foods = []
      const foodCount = Math.floor(Math.random() * 31) + 20 // 20-50个食物，适应大地图

      for (let i = 0; i < foodCount; i++) {
        let newFood
        let attempts = 0
        do {
          newFood = {
            x: Math.random() * (this.mapWidth - 40) + 20,
            y: Math.random() * (this.mapHeight - 40) + 20,
            id: Date.now() + Math.random(),
            spawnTime: Date.now()
          }
          attempts++
        } while (
            attempts < 50 && // 最多尝试50次，避免无限循环
            (this.isPositionOnSnake(newFood.x, newFood.y) ||
                this.isPositionTooCloseToOtherFoods(newFood.x, newFood.y) ||
                this.isPositionTooCloseToPowerUps(newFood.x, newFood.y))
            )

        if (attempts < 50) {
          this.foods.push(newFood)
        }
      }
    },

    // 检查位置是否太靠近其他食物
    isPositionTooCloseToOtherFoods(x, y) {
      return this.foods.some(food => {
        const distance = Math.sqrt((food.x - x) ** 2 + (food.y - y) ** 2)
        return distance < 25
      })
    },

    // 检查位置是否太靠近道具
    isPositionTooCloseToPowerUps(x, y) {
      return this.powerUps.some(powerUp => {
        const distance = Math.sqrt((powerUp.x - x) ** 2 + (powerUp.y - y) ** 2)
        return distance < 30
      })
    },

    // 开始食物刷新定时器
    startFoodRefresh() {
      const refreshFoods = () => {
        if (this.gameState === 'playing') {
          this.generateFoods()
          this.foodRefreshCountdown = this.foodRefreshInterval

          // 继续下一次刷新
          this.foodRefreshTimer = setTimeout(refreshFoods, this.foodRefreshInterval)
        }
      }

      // 5秒后开始第一次刷新
      this.foodRefreshTimer = setTimeout(refreshFoods, this.foodRefreshInterval)
    },

    // 更新食物刷新倒计时
    updateFoodRefreshCountdown() {
      if (this.gameState === 'playing') {
        this.foodRefreshCountdown -= 16
        if (this.foodRefreshCountdown < 0) {
          this.foodRefreshCountdown = 0
        }
      }
    },

    // 检查位置是否在蛇身上
    isPositionOnSnake(x, y) {
      return this.snake.some(segment => {
        const distance = Math.sqrt((segment.x - x) ** 2 + (segment.y - y) ** 2)
        return distance < 15
      })
    },

    // 生成道具
    generatePowerUp() {
      if (this.powerUps.length >= 5) return // 大地图可以有更多道具

      const types = Object.keys(this.powerUpTypes)
      const type = types[Math.floor(Math.random() * types.length)]

      let newPowerUp
      let attempts = 0
      do {
        newPowerUp = {
          x: Math.random() * (this.mapWidth - 40) + 20,
          y: Math.random() * (this.mapHeight - 40) + 20,
          type: type,
          spawnTime: Date.now()
        }
        attempts++
      } while (
          attempts < 50 &&
          (this.isPositionOnSnake(newPowerUp.x, newPowerUp.y) ||
              this.isPositionTooCloseToFoods(newPowerUp.x, newPowerUp.y) ||
              this.powerUps.some(p => Math.sqrt((p.x - newPowerUp.x) ** 2 + (p.y - newPowerUp.y) ** 2) < 30))
          )

      if (attempts < 50) {
        this.powerUps.push(newPowerUp)

        // 设置道具自动移除定时器
        this.powerUpRemovalTimer = setTimeout(() => {
          if (this.gameState === 'playing') {
            this.powerUps = this.powerUps.filter(p => p.x !== newPowerUp.x || p.y !== newPowerUp.y)
          }
        }, 15000) // 大地图中道具存在时间更长
      }
    },

    // 检查位置是否太靠近食物
    isPositionTooCloseToFoods(x, y) {
      return this.foods.some(food => {
        const distance = Math.sqrt((food.x - x) ** 2 + (food.y - y) ** 2)
        return distance < 30
      })
    },

    // 处理鼠标移动
    handleMouseMove(event) {
      if (this.gameState !== 'playing' || !this.mouseControl) return

      const canvas = this.$refs.gameCanvas
      const rect = canvas.getBoundingClientRect()
      const mouseX = event.clientX - rect.left
      const mouseY = event.clientY - rect.top

      this.mousePosition.x = mouseX
      this.mousePosition.y = mouseY

      // 转换为世界坐标
      const worldMouse = this.screenToWorld(mouseX, mouseY)

      // 计算蛇头到鼠标的方向
      const head = this.snake[0]
      const dx = worldMouse.x - head.x
      const dy = worldMouse.y - head.y
      const distance = Math.sqrt(dx * dx + dy * dy)

      if (distance > 10) {
        this.nextDirection.x = dx / distance
        this.nextDirection.y = dy / distance
      }
    },

    // 鼠标进入画布
    handleMouseEnter(event) {
      this.handleMouseMove(event)
    },

    // 鼠标离开画布
    handleMouseLeave() {
      this.mousePosition.x = null
      this.mousePosition.y = null
    },

    // 更新游戏状态
    update() {
      // 更新食物刷新倒计时
      this.updateFoodRefreshCountdown()

      // 更新方向（平滑过渡）
      if (this.mouseControl) {
        this.direction.x = this.nextDirection.x
        this.direction.y = this.nextDirection.y
      } else {
        this.direction = {...this.nextDirection}
      }

      // 移动蛇头
      const head = {...this.snake[0]}
      head.x += this.direction.x * this.snakeSpeed
      head.y += this.direction.y * this.snakeSpeed

      // 检查大地图边界碰撞（只有碰到大地图边缘才死亡）
      if (head.x < 10 || head.x > this.mapWidth - 10 ||
          head.y < 10 || head.y > this.mapHeight - 10) {
        if (!this.hasActiveEffect('invincible')) {
          this.endGame()
          return
        } else {
          // 边界穿越（无敌状态下）
          if (head.x < 10) head.x = this.mapWidth - 10
          if (head.x > this.mapWidth - 10) head.x = 10
          if (head.y < 10) head.y = this.mapHeight - 10
          if (head.y > this.mapHeight - 10) head.y = 10
        }
      }

      // 检查自身碰撞
      for (let i = 3; i < this.snake.length; i++) {
        const segment = this.snake[i]
        const distance = Math.sqrt((head.x - segment.x) ** 2 + (head.y - segment.y) ** 2)
        if (distance < 12) {
          if (!this.hasActiveEffect('invincible')) {
            this.endGame()
            return
          }
        }
      }

      this.snake[0] = head

      // 更新摄像机位置
      this.updateCamera()

      // 计算最远距离
      const centerX = this.mapWidth / 2
      const centerY = this.mapHeight / 2
      const currentDistance = Math.sqrt((head.x - centerX) ** 2 + (head.y - centerY) ** 2)
      this.maxDistance = Math.max(this.maxDistance, currentDistance)

      // 更新蛇身位置（跟随算法）
      for (let i = 1; i < this.snake.length; i++) {
        const current = this.snake[i]
        const target = this.snake[i - 1]

        const dx = target.x - current.x
        const dy = target.y - current.y
        const distance = Math.sqrt(dx * dx + dy * dy)

        if (distance > this.segmentDistance) {
          const moveRatio = (distance - this.segmentDistance) / distance
          current.x += dx * moveRatio
          current.y += dy * moveRatio
        }
      }

      // 检查食物碰撞
      this.foods = this.foods.filter(food => {
        const foodDistance = Math.sqrt((head.x - food.x) ** 2 + (head.y - food.y) ** 2)
        if (foodDistance < 15) {
          this.score += 10

          // 增加蛇身长度
          const tail = this.snake[this.snake.length - 1]
          this.snake.push({x: tail.x, y: tail.y})

          // 增加游戏速度
          if (this.snakeSpeed < 4) {
            this.snakeSpeed += 0.05
          }

          return false // 移除被吃掉的食物
        }
        return true // 保留未被吃掉的食物
      })

      // 检查道具碰撞
      this.powerUps = this.powerUps.filter(powerUp => {
        const powerUpDistance = Math.sqrt((head.x - powerUp.x) ** 2 + (head.y - powerUp.y) ** 2)
        if (powerUpDistance < 15) {
          this.collectPowerUp(powerUp)
          return false
        }
        // 移除过期道具（15秒后消失）
        return Date.now() - powerUp.spawnTime < 15000
      })

      // 更新道具效果
      this.updatePowerUpEffects()

      // 更新最高分
      if (this.score > this.highScore) {
        this.highScore = this.score
        localStorage.setItem('snakeHighScore', this.highScore.toString())
      }

      // 与服务器同步
      this.sendPlayerAction();
    },

    // 检查是否有特定类型的活跃效果
    hasActiveEffect(type) {
      return this.activeEffects.some(effect => effect.type === type && effect.active)
    },

    // 收集道具 - 使用 Toast 通知
    collectPowerUp(powerUp) {
      const powerUpData = this.powerUpTypes[powerUp.type]
      this.score += powerUpData.points

      if (powerUpData.duration > 0) {
        // 创建新的效果对象
        const newEffect = {
          id: Date.now(),
          active: true,
          type: powerUp.type,
          name: powerUpData.name,
          duration: powerUpData.duration,
          startTime: Date.now(),
          toastId: null
        }

        // 如果已经有同类型的效果，先移除它
        this.activeEffects = this.activeEffects.filter(effect => {
          if (effect.type === powerUp.type) {
            if (effect.toastId) {
              this.removeToast(effect.toastId)
            }
            return false
          }
          return true
        })

        // 添加新效果
        this.activeEffects.push(newEffect)

        // 立即应用效果
        this.applyPowerUpEffect(powerUp.type)

        // 显示道具效果 toast，持续时间等于道具效果时间
        // 保存toast ID以便后续管理
        newEffect.toastId = this.showToast(
            powerUpData.name,
            `效果持续 ${Math.ceil(powerUpData.duration / 1000)} 秒`,
            powerUpData.duration,
            powerUpData.icon,
            powerUpData.color,
            powerUpData.color
        )

        // 设置效果结束定时器
        setTimeout(() => {
          this.endPowerUpEffect(powerUp.type)
        }, powerUpData.duration)
      } else {
        // 瞬时效果（如金币）
        this.showToast(
            powerUpData.name,
            `获得 ${powerUpData.points} 分！`,
            2000,
            powerUpData.icon,
            powerUpData.color,
            powerUpData.color
        )
      }
    },

    // 立即应用道具效果
    applyPowerUpEffect(type) {
      const powerUpData = this.powerUpTypes[type]

      // 应用效果
      if (type === 'speed' || type === 'slow') {
        this.snakeSpeed = powerUpData.effect(this.snakeSpeed)
      }

      // 更新powerUpEffect状态（用于视觉效果）
      this.powerUpEffect = {
        active: true,
        type: type,
        name: powerUpData.name,
        duration: powerUpData.duration,
        startTime: Date.now()
      }
    },

    // 结束道具效果
    endPowerUpEffect(type) {
      // 移除效果
      this.activeEffects = this.activeEffects.filter(effect => {
        if (effect.type === type) {
          // 重置相关状态
          if (type === 'speed' || type === 'slow') {
            this.snakeSpeed = this.powerUpTypes[type].reset()
          }
          return false
        }
        return true
      })

      // 如果没有活跃效果，重置powerUpEffect状态
      if (this.activeEffects.length === 0) {
        this.powerUpEffect = {
          active: false,
          type: '',
          name: '',
          duration: 0,
          startTime: 0
        }
      } else {
        // 否则，显示最近的活跃效果
        const latestEffect = this.activeEffects[this.activeEffects.length - 1]
        this.powerUpEffect = {
          active: true,
          type: latestEffect.type,
          name: this.powerUpTypes[latestEffect.type].name,
          duration: latestEffect.duration,
          startTime: latestEffect.startTime
        }
      }
    },

    // 更新所有道具效果
    updatePowerUpEffects() {
      const now = Date.now()

      // 检查是否有效果到期
      this.activeEffects.forEach(effect => {
        const elapsed = now - effect.startTime
        if (elapsed >= effect.duration) {
          this.endPowerUpEffect(effect.type)
        }
      })
    },

    // 绘制游戏
    draw() {
      const canvas = this.$refs.gameCanvas
      if (!canvas) return

      const ctx = canvas.getContext('2d')
      if (!ctx) return

      // 清空画布
      ctx.clearRect(0, 0, this.viewportWidth, this.viewportHeight)

      // 绘制背景网格
      this.drawBackground(ctx)

      // 首先绘制其他玩家的蛇（在底层）
      this.drawOtherPlayersSnakes(ctx);

      // 绘制平滑移动的蛇
      this.drawSmoothSnake(ctx)

      // 绘制多个食物图标
      this.drawFoodIcons(ctx)

      // 绘制道具图标
      this.drawPowerUpIcons(ctx)

      // 绘制鼠标到蛇头的连线
      if (this.mousePosition.x !== null && this.gameState === 'playing') {
        this.drawMouseLine(ctx)
      }

      // 绘制地图边界指示器
      this.drawMapBoundaryIndicators(ctx)
    },

    // 绘制其他玩家的蛇
    drawOtherPlayersSnakes(ctx) {
      this.players.forEach(player => {
        if (player.id !== this.ws.url && player.snake && player.snake.length > 0) {
          // 使用不同的颜色区分其他玩家
          const playerColor = this.getPlayerColor(player.id);

          player.snake.forEach((segment, index) => {
            const screenPos = this.worldToScreen(segment.x, segment.y);

            // 只绘制视窗内的蛇段
            if (screenPos.x < -50 || screenPos.x > this.viewportWidth + 50 ||
                screenPos.y < -50 || screenPos.y > this.viewportHeight + 50) return;

            const isHead = index === 0;
            const radius = isHead ? 12 : Math.max(8, 12 - index * 0.5);

            // 创建渐变效果
            const gradient = ctx.createRadialGradient(
                screenPos.x, screenPos.y, 0,
                screenPos.x, screenPos.y, radius
            );

            // 其他玩家的蛇使用不同颜色
            gradient.addColorStop(0, playerColor.light);
            gradient.addColorStop(1, playerColor.dark);

            ctx.fillStyle = gradient;
            ctx.beginPath();
            ctx.arc(screenPos.x, screenPos.y, radius, 0, Math.PI * 2);
            ctx.fill();

            // 蛇头标记玩家ID
            if (isHead) {
              ctx.fillStyle = '#FFFFFF';
              ctx.font = '10px Arial';
              ctx.textAlign = 'center';
              ctx.textBaseline = 'middle';
              ctx.fillText(`P${player.id.slice(0, 4)}`, screenPos.x, screenPos.y - 15);
            }
          });
        }
      });
    },
    // 根据玩家ID生成颜色
    getPlayerColor(playerId) {
      // 简单哈希生成稳定颜色
      const hash = playerId.split('').reduce((acc, char) => {
        return char.charCodeAt(0) + ((acc << 5) - acc);
      }, 0);

      const hue = Math.abs(hash % 360);
      return {
        light: `hsl(${hue}, 80%, 60%)`,
        dark: `hsl(${hue}, 80%, 40%)`
      };
    },

    // 绘制背景网格
    drawBackground(ctx) {
      ctx.fillStyle = '#1F2937'
      ctx.fillRect(0, 0, this.viewportWidth, this.viewportHeight)

      // 绘制网格
      ctx.strokeStyle = '#374151'
      ctx.lineWidth = 0.5

      const gridSize = 50
      const startX = -(this.camera.x % gridSize)
      const startY = -(this.camera.y % gridSize)

      // 垂直线
      for (let x = startX; x < this.viewportWidth; x += gridSize) {
        ctx.beginPath()
        ctx.moveTo(x, 0)
        ctx.lineTo(x, this.viewportHeight)
        ctx.stroke()
      }

      // 水平线
      for (let y = startY; y < this.viewportHeight; y += gridSize) {
        ctx.beginPath()
        ctx.moveTo(0, y)
        ctx.lineTo(this.viewportWidth, y)
        ctx.stroke()
      }
    },

    // 绘制地图边界指示器
    drawMapBoundaryIndicators(ctx) {
      ctx.strokeStyle = '#EF4444'
      ctx.lineWidth = 3
      ctx.setLineDash([10, 5])

      // 左边界
      if (this.camera.x <= 20) {
        const x = -this.camera.x
        ctx.beginPath()
        ctx.moveTo(x, 0)
        ctx.lineTo(x, this.viewportHeight)
        ctx.stroke()
      }

      // 右边界
      if (this.camera.x + this.viewportWidth >= this.mapWidth - 20) {
        const x = this.mapWidth - this.camera.x
        ctx.beginPath()
        ctx.moveTo(x, 0)
        ctx.lineTo(x, this.viewportHeight)
        ctx.stroke()
      }

      // 上边界
      if (this.camera.y <= 20) {
        const y = -this.camera.y
        ctx.beginPath()
        ctx.moveTo(0, y)
        ctx.lineTo(this.viewportWidth, y)
        ctx.stroke()
      }

      // 下边界
      if (this.camera.y + this.viewportHeight >= this.mapHeight - 20) {
        const y = this.mapHeight - this.camera.y
        ctx.beginPath()
        ctx.moveTo(0, y)
        ctx.lineTo(this.viewportWidth, y)
        ctx.stroke()
      }

      ctx.setLineDash([])
    },

    // 绘制多个食物图标
    drawFoodIcons(ctx) {
      const time = Date.now()

      this.foods.forEach((food, index) => {
        // 只绘制视窗内的食物
        if (!this.isInViewport(food.x, food.y)) return

        const screenPos = this.worldToScreen(food.x, food.y)
        const pulse = Math.sin(time / 300 + index * 0.5) * 0.1 + 0.9
        const size = 18 * pulse
        const age = time - food.spawnTime
        const freshness = Math.max(0.7, 1 - age / 30000)

        // 绘制食物背景圆圈
        const gradient = ctx.createRadialGradient(
            screenPos.x, screenPos.y, 0,
            screenPos.x, screenPos.y, size + 5
        )
        gradient.addColorStop(0, `rgba(239, 68, 68, ${0.3 * freshness})`)
        gradient.addColorStop(1, 'rgba(239, 68, 68, 0)')

        ctx.fillStyle = gradient
        ctx.beginPath()
        ctx.arc(screenPos.x, screenPos.y, size + 5, 0, Math.PI * 2)
        ctx.fill()

        // 绘制苹果图标
        ctx.save()
        ctx.globalAlpha = freshness
        ctx.font = `${size}px Arial`
        ctx.textAlign = 'center'
        ctx.textBaseline = 'middle'
        ctx.fillStyle = '#EF4444'
        ctx.fillText('🍎', screenPos.x, screenPos.y)

        // 添加光晕效果
        ctx.shadowColor = '#EF4444'
        ctx.shadowBlur = 8 * pulse * freshness
        ctx.fillText('🍎', screenPos.x, screenPos.y)
        ctx.shadowBlur = 0
        ctx.restore()
      })
    },

    // 绘制道具图标
    drawPowerUpIcons(ctx) {
      const time = Date.now()

      this.powerUps.forEach(powerUp => {
        // 只绘制视窗内的道具
        if (!this.isInViewport(powerUp.x, powerUp.y)) return

        const screenPos = this.worldToScreen(powerUp.x, powerUp.y)
        const powerUpData = this.powerUpTypes[powerUp.type]
        const age = time - powerUp.spawnTime
        const opacity = age > 10000 ? 0.5 + 0.5 * Math.sin(time / 100) : 1
        const bounce = Math.sin(time / 200 + powerUp.x) * 3
        const size = 18 + Math.sin(time / 300) * 2

        ctx.save()
        ctx.globalAlpha = opacity

        // 绘制背景光圈
        const gradient = ctx.createRadialGradient(
            screenPos.x, screenPos.y + bounce, 0,
            screenPos.x, screenPos.y + bounce, size + 5
        )
        gradient.addColorStop(0, powerUpData.color + '40')
        gradient.addColorStop(1, powerUpData.color + '00')

        ctx.fillStyle = gradient
        ctx.beginPath()
        ctx.arc(screenPos.x, screenPos.y + bounce, size + 5, 0, Math.PI * 2)
        ctx.fill()

        // 绘制道具图标
        ctx.font = `${size}px Arial`
        ctx.textAlign = 'center'
        ctx.textBaseline = 'middle'
        ctx.fillStyle = powerUpData.color
        ctx.fillText(powerUpData.icon, screenPos.x, screenPos.y + bounce)

        // 添加光晕效果
        ctx.shadowColor = powerUpData.color
        ctx.shadowBlur = 15
        ctx.fillText(powerUpData.icon, screenPos.x, screenPos.y + bounce)
        ctx.shadowBlur = 0

        ctx.restore()
      })
    },

    // 绘制鼠标连线
    drawMouseLine(ctx) {
      const head = this.snake[0]
      const headScreen = this.worldToScreen(head.x, head.y)
      const alpha = 0.3

      ctx.strokeStyle = `rgba(34, 211, 238, ${alpha})`
      ctx.lineWidth = 2
      ctx.setLineDash([5, 5])
      ctx.beginPath()
      ctx.moveTo(headScreen.x, headScreen.y)
      ctx.lineTo(this.mousePosition.x, this.mousePosition.y)
      ctx.stroke()
      ctx.setLineDash([])
    },

    // 绘制平滑移动的蛇
    drawSmoothSnake(ctx) {
      this.snake.forEach((segment, index) => {
        const screenPos = this.worldToScreen(segment.x, segment.y)

        // 只绘制视窗内的蛇段
        if (screenPos.x < -50 || screenPos.x > this.viewportWidth + 50 ||
            screenPos.y < -50 || screenPos.y > this.viewportHeight + 50) return

        const isHead = index === 0
        const radius = isHead ? 12 : Math.max(8, 12 - index * 0.5)

        // 创建渐变效果
        const gradient = ctx.createRadialGradient(
            screenPos.x, screenPos.y, 0,
            screenPos.x, screenPos.y, radius
        )

        if (this.hasActiveEffect('invincible')) {
          // 无敌状态闪烁效果
          const flash = Math.sin(Date.now() / 100) * 0.3 + 0.7
          gradient.addColorStop(0, `rgba(139, 92, 246, ${flash})`)
          gradient.addColorStop(1, `rgba(236, 72, 153, ${flash * 0.8})`)
        } else if (isHead) {
          gradient.addColorStop(0, '#10B981')
          gradient.addColorStop(0.7, '#059669')
          gradient.addColorStop(1, '#047857')
        } else {
          const alpha = 1 - (index * 0.05)
          gradient.addColorStop(0, `rgba(52, 211, 153, ${alpha})`)
          gradient.addColorStop(1, `rgba(16, 185, 129, ${alpha * 0.8})`)
        }

        ctx.fillStyle = gradient
        ctx.beginPath()
        ctx.arc(screenPos.x, screenPos.y, radius, 0, Math.PI * 2)
        ctx.fill()

        // 蛇头眼睛和细节
        if (isHead) {
          ctx.fillStyle = '#FFFFFF'
          const eyeSize = 2
          const eyeOffset = 4

          // 根据方向调整眼睛位置
          const angle = Math.atan2(this.direction.y, this.direction.x)
          const eyeX1 = screenPos.x + Math.cos(angle + Math.PI / 4) * eyeOffset
          const eyeY1 = screenPos.y + Math.sin(angle + Math.PI / 4) * eyeOffset
          const eyeX2 = screenPos.x + Math.cos(angle - Math.PI / 4) * eyeOffset
          const eyeY2 = screenPos.y + Math.sin(angle - Math.PI / 4) * eyeOffset

          ctx.beginPath()
          ctx.arc(eyeX1, eyeY1, eyeSize, 0, Math.PI * 2)
          ctx.fill()
          ctx.beginPath()
          ctx.arc(eyeX2, eyeY2, eyeSize, 0, Math.PI * 2)
          ctx.fill()
        }
      })
    },

    // 绘制小地图
    drawMiniMap() {
      const canvas = this.$refs.miniMapCanvas
      if (!canvas) return

      const ctx = canvas.getContext('2d')
      if (!ctx) return

      const miniMapWidth = 200
      const miniMapHeight = 120
      const scaleX = miniMapWidth / this.mapWidth
      const scaleY = miniMapHeight / this.mapHeight

      // 清空小地图
      ctx.clearRect(0, 0, miniMapWidth, miniMapHeight)
      ctx.fillStyle = '#1F2937'
      ctx.fillRect(0, 0, miniMapWidth, miniMapHeight)

      // 绘制地图边界
      ctx.strokeStyle = '#EF4444'
      ctx.lineWidth = 2
      ctx.strokeRect(0, 0, miniMapWidth, miniMapHeight)

      // 绘制视窗位置
      const viewportX = this.camera.x * scaleX
      const viewportY = this.camera.y * scaleY
      const viewportW = this.viewportWidth * scaleX
      const viewportH = this.viewportHeight * scaleY

      ctx.strokeStyle = '#22D3EE'
      ctx.lineWidth = 2
      ctx.strokeRect(viewportX, viewportY, viewportW, viewportH)

      // 绘制蛇头位置
      if (this.snake.length > 0) {
        const head = this.snake[0]
        const headX = head.x * scaleX
        const headY = head.y * scaleY

        ctx.fillStyle = '#10B981'
        ctx.beginPath()
        ctx.arc(headX, headY, 3, 0, Math.PI * 2)
        ctx.fill()
      }

      // 绘制食物位置（小点）
      ctx.fillStyle = '#EF4444'
      this.foods.forEach(food => {
        const foodX = food.x * scaleX
        const foodY = food.y * scaleY
        ctx.beginPath()
        ctx.arc(foodX, foodY, 1, 0, Math.PI * 2)
        ctx.fill()
      })

      // 绘制道具位置
      this.powerUps.forEach(powerUp => {
        const powerUpData = this.powerUpTypes[powerUp.type]
        const powerUpX = powerUp.x * scaleX
        const powerUpY = powerUp.y * scaleY

        ctx.fillStyle = powerUpData.color
        ctx.beginPath()
        ctx.arc(powerUpX, powerUpY, 2, 0, Math.PI * 2)
        ctx.fill()
      })
    },

    // 游戏主循环
    runGameLoop() {
      if (this.gameState !== 'playing') return

      this.update()
      this.draw()
      this.drawMiniMap()
    },

    // 开始游戏循环
    startGameLoop() {
      const gameLoop = () => {
        if (this.gameState !== 'playing') return

        this.runGameLoop()
        this.frameId = requestAnimationFrame(gameLoop)
      }

      this.frameId = requestAnimationFrame(gameLoop)
    },

    // 开始道具生成
    startPowerUpSpawn() {
      const spawnPowerUp = () => {
        if (this.gameState === 'playing') {
          if (Math.random() < 0.4) { // 大地图中道具生成概率稍高
            this.generatePowerUp()
          }

          // 继续生成道具的定时器
          this.powerUpSpawnTimer = setTimeout(spawnPowerUp, Math.random() * 4000 + 3000)
        }
      }

      // 3秒后开始生成道具
      this.powerUpSpawnTimer = setTimeout(spawnPowerUp, 3000)
    },

    // 处理键盘输入
    handleKeyPress(event) {
      if (this.gameState === 'paused' && event.code === 'Space') {
        this.togglePause()
        return
      }

      if (this.gameState !== 'playing') return

      // 键盘控制时禁用鼠标控制
      this.mouseControl = false

      switch (event.code) {
        case 'ArrowUp':
        case 'KeyW':
          this.nextDirection = {x: 0, y: -1}
          break
        case 'ArrowDown':
        case 'KeyS':
          this.nextDirection = {x: 0, y: 1}
          break
        case 'ArrowLeft':
        case 'KeyA':
          this.nextDirection = {x: -1, y: 0}
          break
        case 'ArrowRight':
        case 'KeyD':
          this.nextDirection = {x: 1, y: 0}
          break
        case 'Space':
          this.togglePause()
          break
      }
      event.preventDefault()

      // 2秒后重新启用鼠标控制
      setTimeout(() => {
        this.mouseControl = true
      }, 2000)
    },

    // 改变方向（移动端）
    changeDirection(dir) {
      if (this.gameState !== 'playing') return

      this.mouseControl = false

      switch (dir) {
        case 'up':
          this.nextDirection = {x: 0, y: -1}
          break
        case 'down':
          this.nextDirection = {x: 0, y: 1}
          break
        case 'left':
          this.nextDirection = {x: -1, y: 0}
          break
        case 'right':
          this.nextDirection = {x: 1, y: 0}
          break
      }

      // 2秒后重新启用鼠标控制
      setTimeout(() => {
        this.mouseControl = true
      }, 2000)
    },

    // 结束游戏
    endGame() {
      this.gameState = 'gameOver'
      const deathData = JSON.stringify({ type: 'playerDeath', playerId: this.ws.url });
      if (this.ws.readyState === WebSocket.OPEN) {
        this.ws.send(deathData);
      }
      this.clearAllTimers()
    },

    // 返回菜单
    backToMenu() {
      this.gameState = 'menu'
      this.clearAllTimers()
      // 清除所有 toast
      this.toasts = []
    }
  },
  watch: {
    nextDirection: {
      handler:  function() {
        this.sendPlayerAction();
      },
      deep: true
    }
  }
}
</script>

<style>
@keyframes fade-in {
  from { opacity: 0; transform: translateY(20px); }
  to { opacity: 1; transform: translateY(0); }
}

.animate-fade-in {
  animation: fade-in 0.6s ease-out;
}

canvas:focus {
  outline: none;
}

canvas {
  max-width: 100%;
  height: auto;
}

body {
  margin: 0;
  padding: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}

button {
  cursor: pointer;
  touch-action: manipulation;
}

/* Tailwind CSS 类 */
.bg-gradient-to-br { background-image: linear-gradient(to bottom right, #581c87, #1e3a8a, #312e81); }
.min-h-screen { min-height: 100vh; }
.flex { display: flex; }
.items-center { align-items: center; }
.justify-center { justify-content: center; }
.p-4 { padding: 1rem; }
.top-4 { top: 1rem; }
.right-4 { right: 1rem; }
.z-50 { z-index: 50; }
.space-y-2 > :not([hidden]) ~ :not([hidden]) { margin-top: 0.5rem; }
.bg-white\/90 { background-color: rgba(255, 255, 255, 0.9); }
.backdrop-blur-sm { backdrop-filter: blur(4px); }
.rounded-lg { border-radius: 0.5rem; }
.shadow-lg { box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1); }
.border-l-4 { border-left-width: 4px; }
.transform { transform: translate(0, 0); }
.transition-all { transition-property: all; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 150ms; }
.duration-300 { transition-duration: 300ms; }
.space-x-3 > :not([hidden]) ~ :not([hidden]) { margin-left: 0.75rem; }
.text-2xl { font-size: 1.5rem; line-height: 2rem; }
.font-bold { font-weight: 700; }
.text-gray-800 { color: #1f2937; }
.text-sm { font-size: 0.875rem; line-height: 1.25rem; }
.text-gray-600 { color: #4b5563; }
.mt-1 { margin-top: 0.25rem; }
.w-full { width: 100%; }
.bg-gray-200 { background-color: #e5e7eb; }
.rounded-full { border-radius: 9999px; }
.h-1 { height: 0.25rem; }
.duration-100 { transition-duration: 100ms; }
.text-xs { font-size: 0.75rem; line-height: 1rem; }
.text-gray-500 { color: #6b7280; }
.text-center { text-align: center; }
.space-y-8 > :not([hidden]) ~ :not([hidden]) { margin-top: 2rem; }
.space-y-4 > :not([hidden]) ~ :not([hidden]) { margin-top: 1rem; }
.text-6xl { font-size: 3.75rem; line-height: 1; }
.text-transparent { color: transparent; }
.bg-clip-text { background-clip: text; }
.bg-gradient-to-r { background-image: linear-gradient(to right, #4ade80, #3b82f6); }
.animate-pulse { animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; }
.text-xl { font-size: 1.25rem; line-height: 1.75rem; }
.text-gray-300 { color: #d1d5db; }
.bg-black\/30 { background-color: rgba(0, 0, 0, 0.3); }
.rounded-2xl { border-radius: 1rem; }
.p-6 { padding: 1.5rem; }
.border { border-width: 1px; }
.border-white\/20 { border-color: rgba(255, 255, 255, 0.2); }
.mb-4 { margin-bottom: 1rem; }
.text-white { color: #ffffff; }
.text-4xl { font-size: 2.25rem; line-height: 2.5rem; }
.text-yellow-400 { color: #facc15; }
.grid { display: grid; }
.grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); }
.md\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.gap-4 { gap: 1rem; }
.bg-black\/20 { background-color: rgba(0, 0, 0, 0.2); }
.text-green-400 { color: #4ade80; }
.text-blue-400 { color: #60a5fa; }
.text-purple-400 { color: #c084fc; }
.mt-4 { margin-top: 1rem; }
.text-cyan-400 { color: #22d3ee; }
.text-orange-400 { color: #fb923c; }
.from-green-500 { --tw-gradient-from: #22c55e; }
.to-blue-600 { --tw-gradient-to: #2563eb; }
.hover\:from-green-600:hover { --tw-gradient-from: #16a34a; }
.hover\:to-blue-700:hover { --tw-gradient-to: #1d4ed8; }
.py-4 { padding-top: 1rem; padding-bottom: 1rem; }
.px-8 { padding-left: 2rem; padding-right: 2rem; }
.hover\:scale-105:hover { transform: scale(1.05); }
.justify-between { justify-content: space-between; }
.rounded-xl { border-radius: 0.75rem; }
.space-x-6 > :not([hidden]) ~ :not([hidden]) { margin-left: 1.5rem; }
.text-gray-400 { color: #9ca3af; }
.space-x-4 > :not([hidden]) ~ :not([hidden]) { margin-left: 1rem; }
.space-x-2 > :not([hidden]) ~ :not([hidden]) { margin-left: 0.5rem; }
.bg-orange-600\/30 { background-color: rgba(234, 88, 12, 0.3); }
.px-3 { padding-left: 0.75rem; padding-right: 0.75rem; }
.py-2 { padding-top: 0.5rem; padding-bottom: 0.5rem; }
.text-orange-300 { color: #fdba74; }
.text-orange-200 { color: #fed7aa; }
.px-4 { padding-left: 1rem; padding-right: 1rem; }
.transition-colors { transition-property: color, background-color, border-color; }
.bg-red-600 { background-color: #dc2626; }
.hover\:bg-red-700:hover { background-color: #b91c1c; }
.relative { position: relative; }
.border-4 { border-width: 4px; }
.border-white\/30 { border-color: rgba(255, 255, 255, 0.3); }
.from-gray-900 { --tw-gradient-from: #111827; }
.to-gray-800 { --tw-gradient-to: #1f2937; }
.shadow-2xl { box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25); }
.cursor-none { cursor: none; }
.absolute { position: absolute; }
.pointer-events-none { pointer-events: none; }
.inset-0 { top: 0; right: 0; bottom: 0; left: 0; }
.w-3 { width: 0.75rem; }
.h-3 { height: 0.75rem; }
.bg-cyan-400 { background-color: #22d3ee; }
.animate-ping { animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; }
.bg-black\/50 { background-color: rgba(0, 0, 0, 0.5); }
.grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.gap-2 { gap: 0.5rem; }
.max-w-xs { max-width: 20rem; }
.mx-auto { margin-left: auto; margin-right: auto; }
.md\:hidden { display: none; }
.bg-white\/20 { background-color: rgba(255, 255, 255, 0.2); }
.hover\:bg-white\/30:hover { background-color: rgba(255, 255, 255, 0.3); }
.py-3 { padding-top: 0.75rem; padding-bottom: 0.75rem; }
.text-5xl { font-size: 3rem; line-height: 1; }
.text-red-500 { color: #ef4444; }
.animate-bounce { animation: bounce 1s infinite; }
.flex-col { flex-direction: column; }
.sm\:flex-row { flex-direction: row; }
.to-pink-600 { --tw-gradient-to: #db2777; }
.from-purple-500 { --tw-gradient-from: #a855f7; }
.hover\:from-purple-600:hover { --tw-gradient-from: #9333ea; }
.hover\:to-pink-700:hover { --tw-gradient-to: #be185d; }
.text-lg { font-size: 1.125rem; line-height: 1.75rem; }
.px-6 { padding-left: 1.5rem; padding-right: 1.5rem; }
.pointer-events-auto { pointer-events: auto; }
.flex-1 { flex: 1 1 0; }
.border-2 { border-width: 2px; }

@keyframes pulse {
  50% { opacity: .5; }
}

@keyframes ping {
  75%, 100% {
    transform: scale(2);
    opacity: 0;
  }
}

@keyframes bounce {
  0%, 100% {
    transform: translateY(-25%);
    animation-timing-function: cubic-bezier(0.8,0,1,1);
  }
  50% {
    transform: none;
    animation-timing-function: cubic-bezier(0,0,0.2,1);
  }
}

@media (min-width: 768px) {
  .md\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .md\:hidden { display: none; }
}

@media (min-width: 640px) {
  .sm\:flex-row { flex-direction: row; }
}
</style>